// 引入事件总线，用于组件间通信
import eventBus from "@/utils/eventBus"; // 全局事件总线
// 引入生成唯一ID的工具函数
import { uniqueId } from '@/utils'
// 定义全局变量用于记录拖拽连线的起点、终点等状态
let startPoint = null // 连线起点坐标
let startItem = null  // 连线起点节点
let endPoint = {}     // 连线终点坐标
let activeItem = null // 当前激活的锚点 shape
let curInPoint = null // 当前输入锚点 shape

export default {
    // 注册需要监听的事件
    getEvents() {
        return {
            mousemove: 'onMousemove', // 鼠标移动
            mouseup: 'onMouseup',     // 鼠标松开
            'node:mouseover': 'onMouseover', // 节点鼠标移入
            'node:mouseleave': 'onMouseleave' // 节点鼠标移出
        };
    },
    /**
     * 鼠标松开时的处理逻辑
     * @param {Object} e - 鼠标事件对象
     */
    onMouseup(e) {
        const item = e.item
        // 如果松开时在节点上
        if (item && item.getType() === 'node') {
            const group = item.getContainer()
            // 判断是否在节点的输入锚点上
            if (e.target._attrs.isInPoint) {
                const children = group._cfg.children
                children.map(child => {
                    if (child._attrs.isInPointOut && child._attrs.parent === e.target._attrs.id) {
                        activeItem = child
                    }
                })
                curInPoint = e.target
            } else if (e.target._attrs.isInPointOut) {
                // 如果在输出锚点上
                activeItem = e.target
                const children = group._cfg.children
                children.map(child => {
                    if (child._attrs.isInPoint && child._attrs.id === e.target._attrs.parent) {
                        curInPoint = child
                    }
                })
            }
            // 如果找到了有效的锚点
            if (activeItem) {
                const endX = parseInt(curInPoint._attrs.x)
                const endY = parseInt(curInPoint._attrs.y)
                endPoint = { x: endX, y: endY };
                // 如果存在临时边，则移除并添加新边
                if (this.edge) {
                    this.graph.removeItem(this.edge); // 移除临时边
                    const model = {
                        id: 'edge' + uniqueId(), // 边的唯一ID
                        source: startItem,      // 起始节点对象
                        target: item,           // 目标节点对象
                        sourceId: startItem._cfg.id, // 起点ID
                        targetId: item._cfg.id,      // 终点ID
                        start: startPoint,      // 起点坐标
                        end: endPoint,          // 终点坐标
                        shape: 'customEdge',    // 边的形状
                        type: 'edge'            // 类型
                    }
                    // 通过事件总线通知添加边
                    eventBus.$emit('addItem', model)
                }
            } else {
                // 没有有效锚点则移除临时边
                if (this.edge)
                    this.graph.removeItem(this.edge);
            }
        } else {
            // 没有在节点上则移除临时边
            if (this.edge)
                this.graph.removeItem(this.edge);
        }
        // 恢复所有节点锚点的透明度和样式
        this.graph.find("node", node => {
            const group = node.get('group')
            const children = group._cfg.children
            children.map(child => {
                if (child._attrs.isInPointOut) {
                    child.attr("opacity", "0")
                }
                if (child._attrs.isInPoint) {
                    child.attr("opacity", "0")
                }
                if (child._attrs.isOutPoint) {
                    child.attr("opacity", "0")
                    child.attr("fill", "#fff")
                }
            })
        })
        // 取消起始节点的 hover 状态
        if (startItem) {
            this.graph.setItemState(startItem, 'hover', false);
        }
        // 重新渲染画布
        this.graph.paint()
        // 重置全局变量
        startPoint = null
        startItem = null
        endPoint = {}
        activeItem = null
        curInPoint = null
        // 恢复默认模式
        this.graph.setMode('default')
    },
    /**
     * 鼠标移动时的处理逻辑
     * @param {Object} e - 鼠标事件对象
     */
    onMousemove(e) {
        const item = e.item
        // 第一次移动时，初始化起点和临时边
        if (!startPoint) {
            // 高亮所有节点的输入锚点
            this.graph.find("node", node => {
                const group = node.get('group')
                const children = group._cfg.children
                children.map(child => {
                    if (child._attrs.isInPointOut) {
                        child.attr("opacity", "0.3") // 输出锚点外圈半透明
                    }
                    if (child._attrs.isInPoint) {
                        child.attr("opacity", "1") // 输入锚点高亮
                    }
                })
            })
            const startX = parseInt(e.target._attrs.x)
            const startY = parseInt(e.target._attrs.y)
            startPoint = { x: startX, y: startY };
            startItem = item
            // 添加一条临时边，起点和终点都为当前点
            this.edge = this.graph.addItem('edge', {
                source: item,
                target: item,
                start: startPoint,
                end: startPoint,
                shape: 'link-edge'
            });
        } else {
            // 已经有起点，更新临时边的终点为当前鼠标位置
            const point = { x: e.x, y: e.y };
            if (this.edge) {
                // 增加边的过程中，移动时边跟着移动
                this.graph.updateItem(this.edge, {
                    //  start: startPoint,
                    target: point
                });
            }
        }
    },
    /**
     * 节点鼠标移入时的处理逻辑
     * @param {Object} e - 鼠标事件对象
     */
    onMouseover(e) {
        const item = e.item
        if (item && item.getType() === 'node') {
            // 如果是输出锚点，做动画效果
            if (e.target._attrs.isInPointOut && !this.hasTran) {
                this.hasTran = true
                e.target.transform([
                    ['t', 0, 3], // 平移
                    ['s', 1.2, 1.2], // 缩放
                ])
            }
            this.graph.paint()
        }
    },
    /**
     * 节点鼠标移出时的处理逻辑
     */
    onMouseleave() {
        this.graph.find("node", node => {
            const group = node.get('group')
            const children = group._cfg.children
            children.map(child => {
                if (child._attrs.isInPointOut) {
                    child.resetMatrix() // 还原变换
                }
            })
        })
        this.hasTran = false
        this.graph.paint()
    }
}
